package com.xuecheng.content.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;


import com.xuecheng.api.content.model.CourseBaseDTO;
import com.xuecheng.api.content.model.qo.QueryCourseModel;
import com.xuecheng.api.content.model.vo.CourseBaseVO;
import com.xuecheng.api.content.teachplan.dto.TeachplanDTO;
import com.xuecheng.api.system.model.dto.CourseCategoryDTO;
import com.xuecheng.common.constant.CoursePubTemplateKey;
import com.xuecheng.common.domain.code.CommonErrorCode;
import com.xuecheng.common.domain.page.PageRequestParams;
import com.xuecheng.common.domain.page.PageVO;
import com.xuecheng.common.domain.response.RestResponse;
import com.xuecheng.common.enums.common.CommonEnum;
import com.xuecheng.common.enums.content.CourseAuditEnum;
import com.xuecheng.common.enums.content.CourseChargeEnum;
import com.xuecheng.common.enums.content.CourseModeEnum;
import com.xuecheng.common.exception.ExceptionCast;
import com.xuecheng.common.util.JsonUtil;
import com.xuecheng.common.util.StringUtil;
import com.xuecheng.content.ContentApplication;
import com.xuecheng.content.agent.SystemApiAgent;
import com.xuecheng.content.common.constant.ContentErrorCode;
import com.xuecheng.content.controller.CourseAudController;
import com.xuecheng.content.convert.CourseBaseConvert;
import com.xuecheng.content.convert.CoursePubConvert;
import com.xuecheng.content.entity.CourseBase;
import com.xuecheng.content.entity.CourseMarket;
import com.xuecheng.content.entity.CoursePub;
import com.xuecheng.content.mapper.CourseBaseMapper;
import com.xuecheng.content.service.CourseBaseService;
import com.xuecheng.content.service.CourseMarketService;
import com.xuecheng.content.service.CoursePubService;
import com.xuecheng.content.service.TeachplanService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 课程基本信息 服务实现类
 * </p>
 *
 * @author xuan
 */
@Slf4j
@Service
public class CourseBaseServiceImpl extends ServiceImpl<CourseBaseMapper, CourseBase> implements CourseBaseService {

    @Autowired
    private CourseBaseService courseBaseService;

    @Autowired
    private TeachplanService teachplanService;

    @Autowired
    private SystemApiAgent systemApiAgent;

    @Autowired
    private CoursePubService coursePubService;

    @Autowired
    private CourseMarketService courseMarketService;
    //步骤分析：
    //      1.是否需要开启事务
    //      2.判断关键数据
    //           分页数据
    //           查询条件
    //      3.构建mp分页对象
    //      4.构建查询条件对象LambdaQueryWrapper
    //      5.查询数据
    //      6.获得数据并封装返回结果
    //           封装PageVo数据

    /**
     * @param params 分页数据
     * @param model  课程状态和名称
     * @return
     */
    public PageVO<CourseBaseDTO> queryCourseList(PageRequestParams params, QueryCourseModel model, Long aLong) {

        //1.判断业务数据 判断是否输入了负数 假如小于一就变成一
        if (params.getPageNo() < 1) {
            params.setPageNo(PageRequestParams.DEFAULT_PAGE_NUM);
        }

        if (params.getPageSize() < 1) {
            params.setPageSize(PageRequestParams.DEFAULT_PAGE_SIZE);
        }

        LambdaQueryWrapper<CourseBase> wrapper = new LambdaQueryWrapper<>();
        //2.判断条件查询数据 如果有数据在sql中添加条件
        wrapper.eq(CourseBase::getStatus,CommonEnum.USING_FLAG.getCodeInt());

        if (StringUtil.isNotBlank(model.getCourseName())) {
            wrapper.like(CourseBase::getName, model.getCourseName());
        }

        if (StringUtil.isNotBlank(model.getAuditStatus())) {
            wrapper.eq(CourseBase::getAuditStatus, model.getAuditStatus());
        }

        if (!(ObjectUtils.nullSafeEquals(aLong, CourseAudController.OPERATION_FLAG
                ))) {
            wrapper.eq(CourseBase::getCompanyId, aLong);
        }




        //3.创建分页数据
        Page<CourseBase> page = new Page<>(params.getPageNo(), params.getPageSize());

        //4.根据分页和查询调价查询list数据
        Page<CourseBase> basePage = this.page(page, wrapper);


        List<CourseBase> records = basePage.getRecords();
        long total = basePage.getTotal();

        //4.1将po数据转换为dto
        List<CourseBaseDTO> dtos = Collections.emptyList();
        if (!(CollectionUtils.isEmpty(records))) {
            dtos = CourseBaseConvert.INSTANCE.entitys2dtos(records);
        }

        //5.将查询的结果放到PageVo里面
        /**
         * 1.当前页的集合数据
         * 2.数据库中的总条数
         * 3.当前页码
         * 4.每页条数
         */
        PageVO pageVO = new PageVO(dtos, total, params.getPageNo(), params.getPageSize());


        return pageVO;
    }

    /**
     * 业务分析：
     * 1. 是否开启事务
     * 2. 对关键数据进行判断
     * 有此数据才能进行操作 一般是前端传入
     * 所要判断不能为空的数据来源有三个
     * 前端from表单 数据库约束 api文档
     * 3. 判断业务数据（添加业务没有业务数据判断）
     * 4.  判断是否有数据需要被赋值
     * 有两个属性需要被赋值  status已经被自动赋值了
     * 审核状态 auditStatus：新添加的课程默认审核状态--未提交（状态码）
     * 5. 在业务中需要把dto转为po数据
     * 因为mp的api只能对po数据进行操作
     * 6. 保持数据并返回结果 判断结果是否成功（记得还有两个价格数据在CourseBaseDTO）
     * 7.  如果操作成功 将数据转换成dto并返回
     *
     * @param dto
     * @return
     */
    @Transactional
    public CourseBaseDTO createCourseBase(CourseBaseDTO dto) {
        //2. 对关键数据进行判断
        //     有此数据才能进行操作 一般是前端传入
        //     所要判断不能为空的数据来源有三个
        //         前端from表单 数据库约束 api文档
        verifyCourseMsg(dto);


        //3. 判断业务数据（添加业务没有业务数据判断）
        //4.  判断是否有数据需要被赋值
        //     有两个属性需要被赋值  status已经被自动赋值了
        //     审核状态 auditStatus：新添加的课程默认审核状态--未提交（状态码）
        dto.setAuditStatus(CourseAuditEnum.AUDIT_UNPAST_STATUS.getCode());
        //5. 在业务中需要把dto转为po数据
        //       因为mp的api只能对po数据进行操作
        CourseBase courseBase = CourseBaseConvert.INSTANCE.dtoEntity2to(dto);
        //6. 保持数据并返回结果 判断结果是否成功（记得还有两个价格数据在CourseBaseDTO）
        boolean save = this.save(courseBase);
        if (!save) {
            //throw new RuntimeException("保存数据失败");
            ExceptionCast.cast(ContentErrorCode.E_120001);
        }
        //6.2课程营销信息
        CourseMarket courseMarket = new CourseMarket();
        courseMarket.setCourseId(courseBase.getId());
        courseMarket.setCharge(dto.getCharge());
        //6.3对收费课程进行数据上的判断
        if (CourseChargeEnum.CHARGE_YES.equals(dto.getCharge())) {
            //如果是收费的 价格就不能为空
            if (ObjectUtils.isEmpty(dto.getPrice())) {
                ExceptionCast.cast(ContentErrorCode.E_120021);
                //throw new RuntimeException("价格不能为空");
            }
            //把前端传回来的数值设置进去
            courseMarket.setPrice(dto.getPrice().floatValue());
        }
        //6.3把课程营销信息也返回
        boolean marketSave = courseMarketService.save(courseMarket);
        if (!marketSave) {
            ExceptionCast.cast(ContentErrorCode.E_120022);
            //throw new RuntimeException("营销信息保存失败");
        }

        //7.  如果操作成功 将数据转换成dto并返回
        //将数据库中的最新消息转为dto

        CourseBaseDTO baseDTO = getLastCourseBaseDTO(dto, courseBase);
        return baseDTO;
    }

    /**
     * 转回前端
     * @param dto
     * @param courseBase
     * @return
     */
    public CourseBaseDTO getLastCourseBaseDTO(CourseBaseDTO dto, CourseBase courseBase) {
        CourseBase id = this.getById(courseBase.getId());
        CourseBaseDTO baseDTO = CourseBaseConvert.INSTANCE.entity2dto(id);
        baseDTO.setPrice(dto.getPrice());
        baseDTO.setCharge(dto.getCharge());
        return baseDTO;
    }

    /**
     * 判断全局关键数据
     * @param dto CourseBaseDTO
     */
    public void verifyCourseMsg(CourseBaseDTO dto) {
        if (ObjectUtils.isEmpty(dto.getCompanyId())) {
            //throw new RuntimeException("公司id不能为空");
            ExceptionCast.cast(ContentErrorCode.E_120018);
        }
        if (StringUtil.isBlank(dto.getName())) {
            ExceptionCast.cast(ContentErrorCode.E_120004);
            //throw new RuntimeException("课程名称不能为空");
        }
        if (StringUtil.isBlank(dto.getMt())) {
            ExceptionCast.cast(ContentErrorCode.E_120002);
           // throw new RuntimeException("课程大分类不能为空");
        }
        if (StringUtil.isBlank(dto.getSt())) {
            ExceptionCast.cast(ContentErrorCode.E_120003);
            //throw new RuntimeException("课程小分类不能为空");
        }
        if (StringUtil.isBlank(dto.getGrade())) {
            ExceptionCast.cast(ContentErrorCode.E_120007);
            //throw new RuntimeException("课程等级不能为空");
        }
        if (StringUtil.isBlank(dto.getTeachmode())) {
            ExceptionCast.cast(ContentErrorCode.E_120006);
            //throw new RuntimeException("课程教学模式不能为空");
        }
        if (StringUtil.isBlank(dto.getUsers())) {
            ExceptionCast.cast(ContentErrorCode.E_120019);
            //throw new RuntimeException("使用人群不能为空");
        }

        if (StringUtil.isBlank(dto.getCharge())) {
            ExceptionCast.cast(ContentErrorCode.E_120020);
            //throw new RuntimeException("课程收费不能为空");
        }
    }

    /**
     * 1.是否开启事务
     * 2.判断关键数据
     * 关键数据
     * courseBaseId 课程基本id
     * companyId  机构id
     * 3.判断业务数据
     * 判断是否存在
     * 判断是否是同一家机构
     * 课程营销
     * 4.查询数据并转换为dto返回
     * 根据id查询课程基本信息
     *
     * @param courseBaseId id
     * @param companyId    公司id
     * @return
     */
    public CourseBaseDTO getByCourseId(Long courseBaseId, Long companyId) {
        //2.判断关键数据
        //    关键数据
        //        courseBaseId id
        //        companyId 公司id
        if (ObjectUtils.isEmpty(courseBaseId) || ObjectUtils.isEmpty(companyId)) {
            ExceptionCast.cast(ContentErrorCode.E_120023);
           // throw new RuntimeException("id不一致无法查询");
        }
        //3.判断业务数据
        //    判断是否存在
        //    判断是否是同一家机构
        //课程营销
        //3.1 判断该基本信息是否存在
        CourseBase courseBase = getCourseBaseByBaseId(courseBaseId, companyId);


        //查询课程营销数据,并设置给dto对象
        LambdaQueryWrapper<CourseMarket> marketQueryWrapper = Wrappers.lambdaQuery(CourseMarket.class);
        marketQueryWrapper.eq(CourseMarket::getCourseId, courseBase.getId());
        CourseMarket dbCourseMarket = this.courseMarketService.getOne(marketQueryWrapper);
        //CourseMarket market = getCourseMarketByCourseId(courseBaseId);
        //4.转换为dto返回
        //根据id查询课程基本信息

        CourseBaseDTO courseBaseDTO = CourseBaseConvert.INSTANCE.entity2dto(courseBase);
        courseBaseDTO.setCharge(dbCourseMarket.getCharge());
       // courseBaseDTO.setPrice(new BigDecimal(dbCourseMarket.getPrice().toString()));

        return courseBaseDTO;
    }

    /**
     * 判断课程营销
     * @param courseBaseId
     * @return
     */
    public CourseMarket getCourseMarketByCourseId( Long courseBaseId) {
        LambdaQueryWrapper<CourseMarket> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CourseMarket::getCourseId, courseBaseId);
        CourseMarket market = courseMarketService.getOne(wrapper);
        if (ObjectUtils.isEmpty(market)) {
            ExceptionCast.cast(ContentErrorCode.E_120024);
            //throw new RuntimeException("课程营销信息不存在");
        }
        return market;
    }

    /**
     * 判断是否存在
     * 判断是否删除
     * 判断是否是同一家机构
     * @param courseBaseId 课程基本信息id
     * @param companyId     机构id
     * @return
     */
    public CourseBase getCourseBaseByBaseId(Long courseBaseId, Long companyId) {
        LambdaQueryWrapper<CourseBase> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CourseBase::getCompanyId, companyId)
                    .eq(CourseBase::getId, courseBaseId);
        CourseBase courseBase = this.getOne(queryWrapper);

        if (ObjectUtils.isEmpty(courseBase)) {
            ExceptionCast.cast(ContentErrorCode.E_120013);
            //throw new RuntimeException("课程不存在");
        }

        if (CommonEnum.DELETE_FLAG.equals(courseBase.getStatus())) {
            ExceptionCast.cast(ContentErrorCode.E_120023);
            //throw new RuntimeException("该基本信息以被删除");
        }
        return courseBase;
    }

    /**1.是否开启事务
     * 2.判断关键数据
     *      判断需要修改的数据 可以使用添加的判断
     *      修改时：课程id是必须存在
     * 3.判断业务数据
     *      课程基本信息
     *          判断是否存在
     *          判断是否删除
     *          判断是否是同一家机构
     *          判断审核状态是否可以修改
     *       课程营销
     * 4.修改课程内容
     *      courseBaseId、companyid、auditstatus、status
     *      课程内容中有些数据是不可更改的 对于这些不可更改的数据我们要把他设置为null
     *   课程营销数据表
     *      charge price
     *    修改数据时要判断修改后的结果
     * 5.返回前端最新的数据并封装为dto返回
     * 修改课程基本信息
     * @param dto CourseBaseDTO
     * @return
     */
    @Transactional
    public CourseBaseDTO modifyCourseBase(CourseBaseDTO dto) {
        //2.判断关键数据
        //     判断需要修改的数据 可以使用添加的判断
        //     修改时：课程id是必须存在
        verifyCourseMsg(dto);
        if (ObjectUtils.isEmpty(dto.getCourseBaseId())) {
            ExceptionCast.cast(ContentErrorCode.E_120009);
            //throw new RuntimeException("修改课程id不能为空");
        }
        //3.判断业务数据
        //课程基本信息
        //   判断是否存在
        //   判断是否删除
        //   判断是否是同一家机构
        //   判断审核状态是否可以修改
        //   课程营销
        getCourseBaseByBaseId(dto.getCourseBaseId(),dto.getCompanyId());

        //判断审核状态是否是可以修改的
        if (CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(dto.getAuditStatus())
            || CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(dto.getAuditStatus())
            || CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(dto.getAuditStatus())
        ) {
            ExceptionCast.cast(ContentErrorCode.E_120011);
            //throw new RuntimeException("在该状态下课程不可修改");
        }
        //  判断 课程营销
        getCourseMarketByCourseId(dto.getCourseBaseId());

        //4.修改课程内容
        //courseBaseId、companyid、auditstatus、status
        //课程内容中有些数据是不可更改的 对于这些不可更改的数据我们要把他设置为null
        CourseBase po = CourseBaseConvert.INSTANCE.dtoEntity2to(dto);
        po.setCompanyId(null);
        po.setAuditStatus(null);
        po.setStatus(null);

        boolean baseResult = this.updateById(po);
        if (!baseResult) {
            ExceptionCast.cast(ContentErrorCode.E_120023);
            //throw new RuntimeException("修改课程失败");
        }
        //课程营销数据表
        // charge price
        LambdaUpdateWrapper<CourseMarket> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(CourseMarket::getCharge,dto.getCharge());
        if (CourseChargeEnum.CHARGE_YES.getCode().equals(dto.getCharge())) {
            if (ObjectUtils.isEmpty(dto.getPrice())) {
                ExceptionCast.cast(ContentErrorCode.E_120020);
                //throw  new RuntimeException("收费课程价格不能为空");
            }
            updateWrapper.set(CourseMarket::getPrice,dto.getPrice());
        }
        updateWrapper.eq(CourseMarket::getCourseId,dto.getCourseBaseId());

        //修改数据时要判断修改后的结果
        boolean update = courseMarketService.update(updateWrapper);
        if (!update) {
            ExceptionCast.cast(ContentErrorCode.E_120027);
            //throw  new RuntimeException("修改营销数据失败");
        }
      //5.返回前端最新的数据并封装
        CourseBaseDTO baseDTO = getLastCourseBaseDTO(dto, po);


        return baseDTO;
    }


    /**
     *1.是否开启事务
     *
     *
     *
     *
     * @param courseBaseId  基本信息id
     * @param companyId 公司id
     * @return
     */
    @Transactional
    public void removeCourseBase(Long courseBaseId, Long companyId) {
        //1.判断关键数据的合法性
        if (ObjectUtils.isEmpty(courseBaseId) || ObjectUtils.isEmpty(companyId)) {
            ExceptionCast.cast(ContentErrorCode.E_120023);
            //throw new RuntimeException("id不一致无法查询");
        }

        //2.根据Id获得课程基础信息并进行相应的判断
        CourseBase courseBase = getById(courseBaseId);
        // 判断课程数据是否存在
        if (ObjectUtils.isEmpty(courseBase)) {
            ExceptionCast.cast(ContentErrorCode.E_120013);
           // throw new RuntimeException("课程数据不存在");
        }


        // 判断是否是同一家机构
        if (!(ObjectUtils.nullSafeEquals(companyId, courseBase.getCompanyId()))) {
            ExceptionCast.cast(ContentErrorCode.E_120028);
            //throw new RuntimeException("无权删除其他机构信息");
        }


        //2.1 获得课程基础信息
        //2.4 判断课程的审核状态
        String auditStatus = courseBase.getAuditStatus();
        if (CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(auditStatus)
                || CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(auditStatus)
                || CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(auditStatus)
        ) {
            ExceptionCast.cast(ContentErrorCode.E_120012);
            //throw new RuntimeException("在该状态下课程不可修改");
        }

        // 3.修改课程信息状态值
        // 修改修改时间

        LambdaUpdateWrapper<CourseBase> wrapper = new LambdaUpdateWrapper<>();
        wrapper.set(CourseBase::getStatus,CommonEnum.DELETE_FLAG.getCodeInt());
        wrapper.set(CourseBase::getChangeDate, LocalDateTime.now());
        wrapper.eq(CourseBase::getId,courseBase.getId());
        boolean update = this.update(wrapper);
        if (!update) {
            ExceptionCast.cast(ContentErrorCode.E_120029);
            //throw new RuntimeException("删除失败");
           // ExceptionCast.cast();
        }


    }

    /**提交审核
     *  业务分析：
     *   1.判断关键数据
     *   2.判断业务数据
     *       课程基础信息
     *           判断是否存在
     *           判断是否是同一家教学机构
     *           判断是否删除
     *           判断审核状态
     *   3.修改课程审核状态
     *       已提交
     * @param courseBaseId courseBaseId
     * @param companyId companyId
     */
    @Transactional
    public void commitCourseBase(Long courseBaseId, Long companyId) {
    //业务分析：
        //  1.判断关键数据
        if (ObjectUtils.isEmpty(courseBaseId)||
            ObjectUtils.isEmpty(companyId)
        ) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        //  2.判断业务数据
        //      课程基础信息
        //          判断是否存在
        //          判断是否是同一家教学机构
        //          判断是否删除
        //          判断审核状态
        getCourseByLogic(companyId,courseBaseId);
        //  3.修改课程审核状态
        LambdaUpdateWrapper<CourseBase> wrapper = new LambdaUpdateWrapper<>();
        wrapper.set(CourseBase::getAuditStatus,CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode())
                .set(CourseBase::getChangeDate,LocalDateTime.now())
                .eq(CourseBase::getId,courseBaseId);
        boolean update = this.update(wrapper);
        if (!update) {
            ExceptionCast.cast(ContentErrorCode.E_120017);
        }

    }



    /**
     *判断业务数据
     *     课程基础信息
     *         判断是否存在
     *         判断是否是同一家教学机构
     *         判断是否删除
     *         判断审核状态
     * @param companyId
     * @param courseBaseId
     */
    private void getCourseByLogic(Long companyId, Long courseBaseId) {

        CourseBase courseBase = getCourseBaseByBaseId(courseBaseId, companyId);

        String auditStatus = courseBase.getAuditStatus();
        if (CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(auditStatus)||
                CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(auditStatus)||
                CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(auditStatus)
        ) {
            ExceptionCast.cast(ContentErrorCode.E_120015);
        }
    }

    /**课程审核
     *      1.判断关键数据
     *     auditMind  auditStatus  courseid
     *
     * 2.判断业务数据
     *     课程基础信息
     *         判断是否存在
     *         判断是否删除
     *         判断审核状态
     *             必须为：已提交
     *     审核状态
     *         运营平台只能给课程审核状态赋值：审核通过、审核未通过
     * 3.修改课程审核信息
     *     auditMind  auditStatus  auditNum（每次+1）
     *
     * @param dto dto
     */
    @Transactional
    public void approve(CourseBaseDTO dto) {
        //     1.判断关键数据
        //    auditMind  auditStatus  courseid
        if (StringUtil.isBlank(dto.getAuditMind()) ||
                StringUtil.isBlank(dto.getAuditStatus())
                || ObjectUtils.isEmpty(dto.getCourseBaseId()))
                 {
             ExceptionCast.cast(CommonErrorCode.E_100101);
        }

        //2.判断业务数据
        //    课程基础信息
        //        判断是否存在
        //        判断是否删除
        //        判断审核状态]
        //            必须为：已提交
        LambdaQueryWrapper<CourseBase> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CourseBase::getId, dto.getCourseBaseId());
        queryWrapper.eq(CourseBase::getStatus, CommonEnum.USING_FLAG.getCodeInt());
        queryWrapper.eq(CourseBase::getAuditStatus, CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode());

       int count = this.count(queryWrapper);

       if (count < 1) {
           ExceptionCast.cast(ContentErrorCode.E_120030);
       }

        //    审核状态
        //        运营平台只能给课程审核状态赋值：审核通过、审核未通过
        String auditStatus = dto.getAuditStatus();
        if (CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(auditStatus)||
                CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(auditStatus)||
                CourseAuditEnum.AUDIT_UNPAST_STATUS.getCode().equals(auditStatus)
        ) {
            ExceptionCast.cast(ContentErrorCode.E_120016);
        }
        //3.修改课程审核信息
        //    auditMind  auditStatus  auditNum（每次+1）

        LambdaUpdateWrapper<CourseBase> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(CourseBase::getAuditMind,dto.getAuditMind())
                .set(CourseBase::getAuditStatus,dto.getAuditStatus())
                //.set(CourseBase::getAuditNums,dto.getAuditNums())
                .set(CourseBase::getChangeDate,LocalDateTime.now())
                .eq(CourseBase::getId,dto.getCourseBaseId());

        boolean result = this.update(updateWrapper);

        if (!result) {
            ExceptionCast.cast(ContentErrorCode.E_120017);
        }
    }

    /**预览 主方法业务
     *  业务分析
     *  1.构建coursePub数据并保存
     *  2.根据coursePub内容构建DataMap数据
     *  3.讲datamap进行返回
     *
     * @param courseId 课程id
     * @param companyId  公司id
     * @return Map
     */
    @Transactional
    public Map<String, Object> previewCourse(Long courseId, Long companyId) {
//        1.构建coursePub数据并保存

       CoursePub coursePub = generateCoursePub(courseId,companyId,false);
//        2.根据coursePub内容构建DataMap数据
         Map<String,Object> dataMap= generateDataMap(coursePub);

//        3.将datamap进行返回
        return dataMap;
    }

    /**
     * 构建coursePub数据并保存
     * @param coursePub coursePub
     * @return Map
     */
    private Map<String, Object> generateDataMap(CoursePub coursePub) {
        //构建数据模型对象
        HashMap<String, Object> dataMap = new HashMap<>();
        //构建coursepub
        dataMap.put(CoursePubTemplateKey.COURSEPUB,coursePub);
        //构建coursemarket
        String marketJsonString = coursePub.getMarket();
        CourseMarket courseMarket = JsonUtil.jsonToObject(marketJsonString, CourseMarket.class);
        dataMap.put(CoursePubTemplateKey.COURSEMARKET,courseMarket);
        //构建课程计划
        String teachplanJsonString = coursePub.getTeachplan();
        TeachplanDTO teachplanDTO = JsonUtil.jsonToObject(teachplanJsonString, TeachplanDTO.class);
        dataMap.put(CoursePubTemplateKey.TEACHPLANNODE,teachplanDTO);
        //构建课程模式
        CourseModeEnum[] values = CourseModeEnum.values();
        dataMap.put(CoursePubTemplateKey.COURSETEACHMODEENUMS,values);


        return dataMap;
    }

    /** 构建CoursePub数据并保存
            业务分析：
            1.判断关键数据
            courseId companyId
            2.判断业务数据
            课程基础信息
            判断是否存在
            判断是否是同一家机构
            判断是否删除
            判断审核状态：教学机构课程预览--未提交、审核未通过
            课程营销
            判断是否存在：根据courseid
            课程计划
            获得课程计划：根据courseId和companyId（树形结构）
            课程教师
            判断教师信息是否存在：一定要确保课程最少有一个教师信息
            课程分类数据并完善Coursepub数据
            调用system服务获得课程分类的名称
            3.保存课程发布数据
            CoursePub数据保存数据库中
            课程基础信息  课程营销  课程计划  课程教师
            4.将coursePub数据返回
     *
     * @param courseId   基本数据id
     * @param companyId 公司id
     * @return
     */
    public CoursePub generateCoursePub(Long courseId, Long companyId,boolean isPublish ) {
       //业务分析：
        //1.判断关键数据
        //courseId companyId
        if (ObjectUtils.isEmpty(courseId)
                || ObjectUtils.isEmpty(companyId)
        ) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }

        //2.判断业务数据
        //课程基础信息
        //判断是否存在
        //判断是否是同一家机构
        //判断是否删除
        CourseBaseDTO courseBase = this.courseBaseService.getByCourseId(courseId, companyId);
        String auditStatus = courseBase.getAuditStatus();
        if (isPublish) {
                //为课程发布表 只有审核通过才可以发布
            if (!(CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(auditStatus))) {
                ExceptionCast.cast(ContentErrorCode.E_120201);
            }


        } else {
            //判断审核状态：教学机构课程预览--未提交、审核未通过
            if (CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(auditStatus)||
                    CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(auditStatus)||
                    CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(auditStatus)
            ) {
                ExceptionCast.cast(ContentErrorCode.E_120015);
            }
        }

        //课程营销
        //判断是否存在：根据courseid
        LambdaQueryWrapper<CourseMarket> courseMarketWrapper = new LambdaQueryWrapper<>();
        courseMarketWrapper.eq(CourseMarket::getCourseId,courseId);
        CourseMarket courseMarket = this.courseMarketService.getOne(courseMarketWrapper);
        if (ObjectUtils.isEmpty(courseMarket)) {
            ExceptionCast.cast(ContentErrorCode.E_120024);

        }

        //课程计划
        //获得课程计划：根据courseId和companyId（树形结构）
        TeachplanDTO teachplanDTO = this.teachplanService.queryTreeNodesByCourseId(courseId, companyId);
        //课程教师
        //判断教师信息是否存在：一定要确保课程最少有一个教师信息

        //课程分类数据并完善Coursepub数据
        //调用system服务获得课程分类的名称
        String mt = courseBase.getMt();
        String st = courseBase.getSt();

        RestResponse<CourseCategoryDTO> mtResponse = systemApiAgent.getCourseCategoryById4s(mt);
        if (!(mtResponse.isSuccessful())) {
            ExceptionCast.castWithCodeAndDesc(mtResponse.getCode(),mtResponse.getMsg());
        }

        RestResponse<CourseCategoryDTO> stResponse = systemApiAgent.getCourseCategoryById4s(st);
        if (!(stResponse.isSuccessful())) {
            ExceptionCast.castWithCodeAndDesc(stResponse.getCode(),stResponse.getMsg());
        }

        CourseCategoryDTO mtEntity = mtResponse.getResult();
        CourseCategoryDTO stEntity = stResponse.getResult();
        //构建coursePub数据并执行保存操作
        //课程基础数据
        CoursePub coursePub = CoursePubConvert.INSTANCE.courseBase2coursePub(courseBase);
        //课程营销数据
        String marketJsonString = JsonUtil.objectTojson(courseMarket);
        coursePub.setMarket(marketJsonString);
        coursePub.setPrice(courseMarket.getPrice());
        coursePub.setCharge(courseMarket.getCharge());
        //课程计划数据
        String teachplanJsonString = JsonUtil.objectTojson(teachplanDTO);

        coursePub.setTeachplan(teachplanJsonString);

        //课程教师
        coursePub.setMtName(mtEntity.getName());
        coursePub.setStName(stEntity.getName());
        //保存数据发布数据
        LambdaQueryWrapper<CoursePub> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CoursePub::getCourseId,courseId)
                .eq(CoursePub::getCompanyId,companyId);
        CoursePub po = coursePubService.getOne(queryWrapper);

        boolean result = false;
        //判断课程发布数据是否存在
        if (ObjectUtils.isEmpty(po)) {
//            如果不存在就创建   创建时要将coursepub和coursebase关联
            coursePub.setCourseId(courseBase.getCompanyId());
            result = coursePubService.save(coursePub);
        } else {
//            如果存在 就修改课程发布数据内容
            coursePub.setId(po.getId());
          result =  coursePubService.updateById(coursePub);
        }
        if (!result) {
            ExceptionCast.cast(ContentErrorCode.E_120205);
        }


        return coursePub;
    }


}
